﻿using System;
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace DevelopersTestPad.Worksheets.DotNet.Interaction
{
    /// <summary>
    /// Represents a writer that can write a sequential series of characters.
    /// </summary>
    [Serializable]
    internal class ConsoleWriter : TextWriter
    {
        /// <summary>
        /// Occurs when a plain text has been written.
        /// </summary>
        internal event EventHandler<ConsoleWriterEventArgs> ReceivePlainText;

        public override Encoding Encoding
        {
            get { return Encoding.Unicode; }
        }

        /// <summary>
        /// Raises the <see cref="ReceivePlainText"/> event.
        /// </summary>
        /// <param name="e">An <see cref="ConsoleWriterEventArgs"/> that contains the event data.</param>
        protected virtual void OnReceivePlainText(ConsoleWriterEventArgs e)
        {
            EventHandler<ConsoleWriterEventArgs> handler = ReceivePlainText;
            if (handler != null)
            {
                handler(this, e);
            }            
        }

        /// <summary>
        /// Occurs when a plain text has been written.
        /// </summary>
        /// <param name="value">Plain text.</param>
        protected virtual void OnWrite(string value)
        {
            OnReceivePlainText(new ConsoleWriterEventArgs { PlainText = value });
        }

        public override void Write(string value)
        {
            OnWrite(value);
        }

        public override void WriteLine()
        {
            Write(Environment.NewLine);
        }

        public override void Write(bool value)
        {
            Write(value.ToString());
        }

        public override void Write(char[] buffer)
        {
            Write(buffer.ToString());
        }

        public override void Write(char[] buffer, int index, int count)
        {
            Write(buffer.ToString().Substring(index, count));
        }

        public override void Write(char value)
        {
            Write(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void Write(decimal value)
        {
            Write(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void Write(double value)
        {
            Write(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void Write(float value)
        {
            Write(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void Write(int value)
        {
            Write(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void Write(long value)
        {
            Write(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void Write(object value)
        {
            Write(value != null ? value.ToString() : null);
        }

        public override void Write(string format, object arg0)
        {
            Write(string.Format(format, arg0));
        }

        public override void Write(string format, object arg0, object arg1)
        {
            Write(string.Format(format, arg0, arg1));
        }

        public override void Write(string format, object arg0, object arg1, object arg2)
        {
            Write(string.Format(format, arg0, arg1, arg2));
        }

        public override void Write(string format, params object[] arg)
        {
            Write(string.Format(format, arg));
        }

        public override void Write(uint value)
        {
            Write(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void Write(ulong value)
        {
            Write(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void WriteLine(string value)
        {
            Write(value + Environment.NewLine);
        }

        public override void WriteLine(bool value)
        {
            WriteLine(value.ToString());
        }

        public override void WriteLine(char[] buffer)
        {
            WriteLine(buffer.ToString());
        }

        public override void WriteLine(char[] buffer, int index, int count)
        {
            WriteLine(buffer.ToString().Substring(index, count));
        }

        public override void WriteLine(char value)
        {
            WriteLine(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void WriteLine(decimal value)
        {
            WriteLine(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void WriteLine(double value)
        {
            WriteLine(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void WriteLine(float value)
        {
            WriteLine(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void WriteLine(int value)
        {
            WriteLine(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void WriteLine(long value)
        {
            WriteLine(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void WriteLine(object value)
        {
            Write(value != null ? value.ToString() : null);
        }

        public override void WriteLine(string format, object arg0)
        {
            WriteLine(string.Format(format, arg0));
        }

        public override void WriteLine(string format, object arg0, object arg1)
        {
            WriteLine(string.Format(format, arg0, arg1));
        }

        public override void WriteLine(string format, object arg0, object arg1, object arg2)
        {
            WriteLine(string.Format(format, arg0, arg1, arg2));
        }

        public override void WriteLine(string format, params object[] arg)
        {
            WriteLine(string.Format(format, arg));
        }

        public override void WriteLine(uint value)
        {
            WriteLine(value.ToString(CultureInfo.CurrentCulture));
        }

        public override void WriteLine(ulong value)
        {
            WriteLine(value.ToString(CultureInfo.CurrentCulture));
        }

        public override Task WriteAsync(char value)
        {
            throw new NotImplementedException();
        }

        public override Task WriteAsync(char[] buffer, int index, int count)
        {
            throw new NotImplementedException();
        }

        public override Task WriteAsync(string value)
        {
            throw new NotImplementedException();
        }

        public override Task WriteLineAsync()
        {
            throw new NotImplementedException();
        }

        public override Task WriteLineAsync(char value)
        {
            throw new NotImplementedException();
        }

        public override Task WriteLineAsync(char[] buffer, int index, int count)
        {
            throw new NotImplementedException();
        }

        public override Task WriteLineAsync(string value)
        {
            throw new NotImplementedException();
        }
    }
}